深入ES6 (三) for...of

for…of

在我学习for..of之前,我一会以为被吹捧的for…of有多么多么吊。。。在学习了之后,我感觉for…of相比较forEach、for来讲,不过尔尔。其实不过是像C++、Java、C# 和 Python 语言一样。

前言

Iterator(遍历器概念)

在讲for…of之前,简单介绍一个概念:Iterator。

Iterator的概念其实并不复杂,它其实像是一个javascript语法中的一个接口,或者说方法,如果想使用遍历功能,就需要调用Iterator遍历器功能。


Iterator的其内部逻辑就不细究了,其大致原理是Iterator接口拥有一个next方法,吐出当前遍历的值并把当前遍历推向下一个位置

1
2
3
4
5
var it = makeIterator(['a', 'b']);
it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }

原生具备 Iterator 接口的数据结构如下。

Array

Map

Set

String

这四个数据类型之所以原生就调用了Iterator接口,是因为这些数据结构原生部署了Symbol.iterator属性,凡是部署了Symbol.iterator属性的数据结构,就称为部署了遍历器接口。调用这个接口,就会返回一个遍历器对象。


如果类似于json这种原生不具备Iterator接口的数据类型,如果想让它具有遍历特性,就需要手动给json部署数组的Symbol.iterator方法

有一点要注意,json的数据结构键值需为按顺序的数字,否则Symbol.iterator识别不了。

1
2
3
4
5
6
7
8
9
10
let iterable = {
0: 'a',
1: 'b',
2: 'c',
length: 3,
[Symbol.iterator]: Array.prototype[Symbol.iterator]
};
for (let item of iterable) {
console.log(item); // 'a', 'b', 'c'
}

for…of

之所以在讲for…of之前要讲一下Iterator,就是因为for..of只可以遍历拥有Iterator特性的结构

1
2
3
4
const arr =[1,2,3,4];
for(let i of arr){
console.log(i)//1,2,3,4
}

1
2
3
4
5
6
7
8
9
10
11
12
const arr = ['red', 'green', 'blue'];
for(let v of arr) {
console.log(v); // red green blue
}
const obj = {};
obj[Symbol.iterator] = arr[Symbol.iterator].bind(arr);
for(let v of obj) {
console.log(v); // red green blue
}

与其他遍历语法的比较

for

for循环是javascript最基础的遍历,不过写起来比较麻烦

1
2
3
for (var index = 0; index < myArray.length; index++) {
console.log(myArray[index]);
}

forEach

forEach的有点在于写起来比for轻松方便很多

但是这种写法的问题在于,无法中途跳出forEach循环,break命令或return命令都不能奏效。

1
2
3
myArray.forEach(function (item,i) {
console.log(value);
});

for in

for…in循环可以遍历数组的键名。

数组的键名是数字,但是for…in循环是以字符串作为键名“0”、“1”、“2”等等。

for…in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。

某些情况下,for…in循环会以任意顺序遍历键名。

for of

有着同for…in一样的简洁语法,但是没有for…in那些缺点。

不同于forEach方法,它可以与break、continue和return配合使用。

提供了遍历所有数据结构的统一操作接口。

总结

简单来说for…of还是有的放矢的,不过相比于其他ES6特性,for..of并没有那么耀眼